package org.papervision3d.core.proto
{
    import flash.geom.Matrix;
    import flash.display.BitmapData;
    
    // The MaterialObject3D class is the base class for all materials.
    // Materials collects data about how objects appear when rendered.
    // A material is data that you assign to objects or faces, so that they appear a certain way when rendered. Materials affect the line and fill colors.
    // Materials create greater realism in a scene. A material describes how an object reflects or transmits light.
    // You assign materials to individual objects or a selection of faces; a single object can contain different materials.
    // MaterialObject3D is an abstract base class; therefore, you cannot call MaterialObject3D directly.
    public class MaterialObject3D
    {
        // A transparent or opaque BitmapData texture.
        public var bitmap:BitmapData;
    
        // A Boolean value that determines whether the texture is animated.
        // If set, the material must be included into the scene so the BitmapData texture can be updated when rendering. For performance reasons, the default value is false.
        public var animated:Boolean;
    
        // A Boolean value that determines whether the BitmapData texture is smoothed when rendered.
        public var smooth:Boolean;
    
        // A RGB color value to draw the faces outline.
        public var lineColor:Number;
    
        // An 8-bit alpha value for the faces outline. If zero, no outline is drawn.
        public var lineAlpha:Number;
    
        // A RGB color value to fill the faces with. Only used if no texture is provided.
        public var fillColor:Number;
    
        // An 8-bit alpha value fill the faces with. If this value is zero and no texture is provided or is undefined, a fill is not created.
        public var fillAlpha:Number;
    
        // A Boolean value that indicates whether the faces are double sided.
        public function get doubleSided():Boolean
        {
            return !this.oneSide;
        }
    
        public function set doubleSided(double:Boolean):void
        {
            this.oneSide = !double;
        }
    
        // A Boolean value that indicates whether the faces are single sided. It has preference over doubleSided.
        public var oneSide:Boolean;
    
        // A Boolean value that indicates whether the faces are invisible (not drawn).
        public var invisible:Boolean;
    
        // A Boolean value that indicates whether the face is flipped. Only used if doubleSided or not singeSided.
        public var opposite:Boolean;
    
        // The scene where the object belongs.
        public var scene:SceneObject3D;
    
        // Default color used for debug.
        static public var DEFAULT_COLOR:Number = 0xFF00FF;
    
        // The name of the material.
        public var name:String;
    
        // [internal-use] [read-only] Unique id of this instance.
        public var id:Number;
        
        /**
		 * Internal use
		 */
		public var maxU :Number;
	
		/**
		 * Internal use
		 */
		public var maxV :Number;

    
        // Creates a new MaterialObject3D object.
        // @param    initObject  [optional] - An object that contains properties for the newly created material.
        public function MaterialObject3D(initObject:Object = null)
        {
            if (initObject && initObject.bitmap) 
                this.bitmap = initObject.bitmap;
    
            // Color
            this.lineColor = initObject ? initObject.lineColor || DEFAULT_COLOR : DEFAULT_COLOR;
            this.lineAlpha = initObject ? initObject.lineAlpha || 0 : 0;
    
            this.fillColor = initObject ? initObject.fillColor || DEFAULT_COLOR : DEFAULT_COLOR;
            this.fillAlpha = initObject ? initObject.fillAlpha || 0 : 0;
    
            this.animated  = initObject ? initObject.animated || false : false;
    
            // Defaults
            this.invisible = initObject ? initObject.invisible || false : false;
            this.smooth    = initObject ? initObject.smooth    || false : false;
                                         
            this.doubleSided = initObject ? initObject.doubleSided || false : false;
            this.opposite = initObject ? initObject.opposite || false : false;

            this.maxU = initObject ? initObject.maxU || 1 : 1;
            this.maxV = initObject ? initObject.maxV || 1 : 1;
    
            this.id = _totalMaterialObjects++;
        }
    
        // Returns a MaterialObject3D object with the default magenta wireframe values.
        // @return A MaterialObject3D object.
        static public function get DEFAULT():MaterialObject3D
        {
            var defMaterial:MaterialObject3D = new MaterialObject3D();
    
            defMaterial.lineColor = DEFAULT_COLOR;
            defMaterial.lineAlpha = 100;
            defMaterial.fillColor = DEFAULT_COLOR;
            defMaterial.fillAlpha = 10;
            defMaterial.doubleSided = true;
    
            return defMaterial;
        }
    
        // Updates the BitmapData bitmap from the given texture.
        // Draws the current MovieClip image onto bitmap.
        public function updateBitmap():void 
        {
        }

        // Copies the properties of a material.
        // @param material Material to copy from.
        public function copy(material:MaterialObject3D):void
        {
            this.bitmap    = material.bitmap;
            this.animated  = material.animated;
            this.smooth    = material.smooth;
    
            this.lineColor = material.lineColor;
            this.lineAlpha = material.lineAlpha;
            this.fillColor = material.fillColor;
            this.fillAlpha = material.fillAlpha;
    
            this.oneSide   = material.oneSide;
            this.opposite  = material.opposite;
    
            this.invisible = material.invisible;
            this.scene     = material.scene;
            this.name      = material.name;
        }
    
        // Creates a copy of the material.
        // @return A newly created material that contains the same properties.
        public function clone():MaterialObject3D
        {
            var cloned:MaterialObject3D = new MaterialObject3D();
    
            cloned.bitmap    = this.bitmap;
            cloned.animated  = this.animated;
            cloned.smooth    = this.smooth;
    
            cloned.lineColor = this.lineColor;
            cloned.lineAlpha = this.lineAlpha;
            cloned.fillColor = this.fillColor;
            cloned.fillAlpha = this.fillAlpha;
    
            cloned.oneSide   = this.oneSide;
            cloned.opposite  = this.opposite;
    
            cloned.invisible = this.invisible;
            cloned.scene     = this.scene;
            cloned.name      = this.name;
    
            return cloned;
        }
    
        // Returns a string value representing the material properties.
        // @return   A string.
        public function toString():String
        {
            return "[MaterialObject3D] bitmap:" + this.bitmap + " lineColor:" + this.lineColor + " fillColor:" + fillColor;
        }
        
        public function dispose() : void {
        	bitmap.dispose();
        }
    
        static private var _totalMaterialObjects:Number = 0;
    }
}
